package me.obstsalat.guildera;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.logging.Logger;

import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;

public class guildera extends JavaPlugin implements Listener {

	public static guildera plugin;
	public final Logger logger = Logger.getLogger("Minecraft"); 
	public final hook_manager hm = new hook_manager(this);
	public final configParser config = new configParser(this);
	
	//remote hooked classes
	public final d_chat i_d_chat = new d_chat(this);
	public final d_protection i_d_protection = new d_protection(this);
	public final g_armor_res i_g_armor_res = new g_armor_res(this);
	public final g_block_res i_g_block_res = new g_block_res(this);
	public final g_chat i_g_chat = new g_chat(this);
	public final g_experience i_g_experience = new g_experience(this);
	public final g_irongolem i_g_irongolem = new g_irongolem(this);
	public final g_tool_res i_g_tool_res = new g_tool_res(this);
	public final g_war i_g_war = new g_war(this);
	
	public World overworld;
	public List<World> worlds = new ArrayList<World>();
	
	public List<guild> guilds = new ArrayList<guild>();
	public List<String> restricted_founders = new ArrayList<String>();
	
	private Timer t_dt_refill = new Timer();
	private Timer t_dt_compass = new Timer();
	private Timer t_gt_guild_save = new Timer();
	private Timer t_gt_villager_drop = new Timer();
	private Timer t_gt_villager_exp = new Timer();
	private Timer t_gt_villager_spawn = new Timer();
	
	public List<Location2d> rA = new ArrayList<Location2d>();
	public List<Treasure> treasures = new ArrayList<Treasure>();
	
	
	@Override
	public void onDisable() {
		PluginDescriptionFile pdfFile = this.getDescription();
		logger.info("[" + pdfFile.getName() + "] Saving data...");
		saverA();
		saveTreasures();
		for(guild g : guilds) {
			g.save(this);
		}
		logger.info("[" + pdfFile.getName() + "] ... complete!");
		logger.info(pdfFile.getName() + " is now disabled.");
	}
	
	@Override
	public void onEnable() {
		PluginDescriptionFile pdfFile = this.getDescription();
		Bukkit.getServer().getPluginManager().registerEvents(hm, this);
		config.load();
		try {
			boolean bl = config.getString("version").equals("rev29");
			if(!bl) {
				logger.info("[" + this.getDescription().getName() + "] The config file is outdated, please update or delete it.");
				logger.info("[" + this.getDescription().getName() + "] Shutting down GuildEra.");
				this.setEnabled(false);
				return;
			}
		} catch (Exception ex) {
			logger.info("[" + this.getDescription().getName() + "] The config file is outdated, please update or delete it.");
			logger.info("[" + this.getDescription().getName() + "] Shutting down GuildEra.");
			this.setEnabled(false);
			return;
		}
		loadWorlds();
		worldLib.initializeInstance(this);
		worldLib.initializeWorld(overworld);
		structureLib.initializeInstance(this);
		structureLib.initializeStructureLib();
		if(config.getBool("use_guilds")) {
			loadGuilds();
			i_g_block_res.overrideTable();
		}
		if(config.getBool("use_dungeons"))  {
			loadrA();
			loadTreasures();
		}
		if(!config.getBool("use_dungeons") && !config.getBool("use_guilds")) {
			logger.info("[" + this.getDescription().getName() + "] GuildEra is disabled in its config.cfg.");
			logger.info("[" + this.getDescription().getName() + "] Shutting down GuildEra.");
			this.setEnabled(false);
			return;
		}
		
		//starting timers
		if(config.getBool("use_dungeons")) {
			t_dt_refill.schedule( new dt_refill(this), 86400000, 86400000);
			if(config.getBool("use_compass")) {
				t_dt_compass.schedule( new dt_compass(this), 30000, 30000);
			}
		}
		if(config.getBool("use_guilds")) {
			t_gt_guild_save.schedule( new gt_guild_save(this), 300000, 300000);
			t_gt_villager_drop.schedule( new gt_villager_drop(this), 1800000, 1800000);
			t_gt_villager_exp.schedule( new gt_villager_exp(this), 21600000, 21600000);
			if(config.getBool("spawn_villagers")) {
				t_gt_villager_spawn.schedule( new gt_villager_spawn(this), 3600000, 3600000);
			}
		}
		
		logger.info(pdfFile.getName() + " " + pdfFile.getVersion() + " is now enabled.");
	}
	
	
	private void loadWorlds() {
		try {
			String path = "";
			File file = null;
			path = getDataFolder().getCanonicalPath();
			file = new File(path);
			if(!file.exists()) {
				file.mkdirs();
			}
			if(path.contains("\\")) { 
				path = getDataFolder().getCanonicalPath() + "\\" + "worlds.cfg";
			}	else {
				path = getDataFolder().getCanonicalPath() + "/" + "worlds.cfg";
			}
			file = new File(path);
			if(file.exists()) {
				logger.info("[" + getDescription().getName() + "] worlds.cfg detected. Loading worlds.");
				BufferedReader in = new BufferedReader(new FileReader(file));
				boolean first = true;
				String str;
				while ((str = in.readLine()) != null) {
					if(first) {
						first = false;
						for(World w : getServer().getWorlds()) {
							if(w.getName().equals(str)) {
								overworld = w;
								worlds.add(w);
							}
						}
					} else {
						for(World w : getServer().getWorlds()) {
							if(w.getName().equals(str)) {
								worlds.add(w);
							}
						}
					}
				}
			} else {
				file.createNewFile();
				logger.info("[" + getDescription().getName() + "] No worlds.cfg detected. Creating new one. Grabbing " + this.getServer().getWorlds().get(0).getName() + " as main world.");
				BufferedWriter out = new BufferedWriter(new FileWriter(file));
				String str = null;
				for(World w : this.getServer().getWorlds()) {
					if(str == null) {
						str = w.getName();
					} else {
						str = str + "\n" + w.getName();
					}
				}
				out.write(str);
				out.close();
				overworld = this.getServer().getWorlds().get(0);
				
			}
		}	catch(Exception exc) {
			logger.info("ERROR: GuildEra.guildera.java:loadStartLevel() " + exc.toString());
		}
	}
	
	public boolean checkViableWorld(World w) {
		boolean check = false;
		for(World ww : worlds) {
			if(ww.getName().equals(w.getName())) {
				check = true;
			}
		}
		return check;
	}
	
	@SuppressWarnings("unchecked")
	private void loadTreasures() {
		try {
			String path = "";
			File file = null;
			path = getDataFolder().getCanonicalPath();
			if(path.contains("\\")) { 
				path = getDataFolder().getCanonicalPath() + "\\" + "loot.treasure";
			}	else {
				path = getDataFolder().getCanonicalPath() + "/" + "loot.treasure";
			}
			file = new File(path);
			if(file.exists()) {
				FileInputStream fis = new FileInputStream(file);
				ObjectInputStream in = new ObjectInputStream(fis);
				treasures = (ArrayList<Treasure>) in.readObject();
				fis.close();
			}
		}	catch(Exception exc) {
			logger.info("ERROR: GuildEra.guildera.java:loadTreasures() " + exc.toString());
		}
	}
	
	public void saveTreasures() {
		String path = "";
		File file = null;
		try {
			path = getDataFolder().getCanonicalPath();
			file = new File(path);
			if(!file.exists()) {
				file.mkdirs();
			}
			if(path.contains("\\")) { 
				path = path + "\\" + "loot.treasure";
			}	else {
				path = path + "/" + "loot.treasure";
			}
			file = new File(path);
			if(!file.exists()) {
				file.createNewFile();
			}
			if(file.exists()) {
				if(!rA.isEmpty()) {
					FileOutputStream fos = new FileOutputStream(file);
					ObjectOutputStream out = new ObjectOutputStream(fos);
					out.writeObject(treasures);
					fos.close();
				} else {
					file.delete();
				}
			}
		} catch(Exception exc) {
			logger.info("ERROR: GuildEra.guildera.java:saveTreasures() " + exc.toString());
		}
	}
	
	private void loadGuilds() {
		try {
			logger.info("[" + this.getDescription().getName() + "] Loading guilds...");
			File f = new File(this.getDataFolder().getCanonicalPath());
			if(f.listFiles() != null) {
				for(File ff : f.listFiles()) {
					if(ff.isDirectory()) {
						guilds.add(new guild(ff.getName(),this));
						logger.info(" - " + ff.getName());
					}
				}
			}
			logger.info("[" + this.getDescription().getName() + "] ... complete!");
		} catch(Exception ex) {
			logger.info("ERROR: GuildEra.guildera.java:loadGuilds() " + ex.getMessage());
		}
	}
	
	public void removeGuild(guild g) {
		try {
			for(int i = 0; i < guilds.size(); i++) {
				if(guilds.get(i).getName().equalsIgnoreCase(g.getName())) {
					guilds.remove(i);
				}
			}
			File file;
			for(Player plx : getServer().getOnlinePlayers()) {
				plx.sendMessage(g.getName() + " has been disbanded.");
			}
			logger.info("[" + getDescription().getName() + "] " + g.getName() + " has been disbanded.");
			String path = "";
			if(getDataFolder().getCanonicalPath().contains("\\")) { 
				path = getDataFolder().getCanonicalPath() + "\\" + g.getName() + "\\";
			}	else {
				path = getDataFolder().getCanonicalPath() + "/" + g.getName() + "/";
			}
			file = new File(path + "ep.guild");
			if(file.exists()) {
				file.delete();
			}
			file = new File(path + "position.guild");
			if(file.exists()) {
				file.delete();
			}
			file = new File(path + "members.guild");
			if(file.exists()) {
				file.delete();
			}
			file = new File(path + "area.guild");
			if(file.exists()) {
				file.delete();
			}
			file = new File(path + "village_manager.guild");
			if(file.exists()) {
				file.delete();
			}
			file = new File(path + "teleport.guild");
			if(file.exists()) {
				file.delete();
			}
			if(getDataFolder().getCanonicalPath().contains("\\")) { 
				path = getDataFolder().getCanonicalPath() + "\\" + g.getName();
			}	else {
				path = getDataFolder().getCanonicalPath() + "/" + g.getName();
			}
			file = new File(path);
			file.delete();
		} catch(Exception ex) {
			logger.info("ERROR: GuildEra.guildera.java:removeGuild() " + ex.toString());
		}
	}
	
	@SuppressWarnings("unchecked")
	private void loadrA() {
		try {
			String path = "";
			File file = null;
			path = getDataFolder().getCanonicalPath();
			if(path.contains("\\")) { 
				path = getDataFolder().getCanonicalPath() + "\\" + "rA.location2d";
			}	else {
				path = getDataFolder().getCanonicalPath() + "/" + "rA.location2d";
			}
			file = new File(path);
			if(file.exists()) {
				FileInputStream fis = new FileInputStream(file);
				ObjectInputStream in = new ObjectInputStream(fis);
				rA = (ArrayList<Location2d>) in.readObject();
				fis.close();
			}
		}	catch(Exception exc) {
			logger.info("ERROR: GuildEra.guildera.java:loadrA() " + exc.toString());
		}
	}
	
	public void saverA() {
		String path = "";
		File file = null;
		try {
			path = getDataFolder().getCanonicalPath();
			file = new File(path);
			if(!file.exists()) {
				file.mkdirs();
			}
			if(path.contains("\\")) { 
				path = path + "\\" + "rA.location2d";
			}	else {
				path = path + "/" + "rA.location2d";
			}
			file = new File(path);
			if(!file.exists()) {
				file.createNewFile();
			}
			if(file.exists()) {
				if(!rA.isEmpty()) {
					FileOutputStream fos = new FileOutputStream(file);
					ObjectOutputStream out = new ObjectOutputStream(fos);
					out.writeObject(rA);
					fos.close();
				} else {
					file.delete();
				}
			}
		} catch(Exception exc) {
			logger.info("ERROR: GuildEra.guildera.java:saverA() " + exc.toString());
		}
	}
	
	
}
